package com.huangfu.learning.javabase.java.java8;

import java.util.*;
import java.util.function.Predicate;
import java.util.stream.Collectors;

/**
 * Created with IntelliJ IDEA.
 * Author: huangfu.daohui
 * Date: 2018/7/21
 * Time: 16:55
 * Version: 1.0
 * Description:Lambda表达式练习
 * https://blog.csdn.net/bitcarmanlee/article/details/70195403
 * https://blog.csdn.net/qq_27093465/article/details/77750806
 * https://blog.csdn.net/u014646662/article/details/52261511
 * https://blog.csdn.net/piglite/article/details/53823584  reduce collect
 **/
public class LambdaPractice {
    public static void main(String[] args) {
        //匿名内部类
        anonymousInnerClass();

        // List遍历
        eachList();

        //map 遍历
        eachMap();

        //filter 对操作集合，按某个条件进行过滤
        streamFilter();

        // map 对集合操作，转换
        streamMap();

        //mapReduce reduce实现的是将所有值合并为一个；
        //Stream.reduce，返回单个的结果值，并且reduce操作每处理一个元素总是创建一个新值。常用的方法有average, sum, min, max, count
        mapReduce();

        // filter+predicate做过滤  predicate条件的意思
        filterPredicate();
    }

    //匿名内部类的两种
    static void anonymousInnerClass() {

        // 老方法
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("switchcase polymorphic thread now is running!");
            }
        }).start();

        // lambda 方法 箭头后面就是run方法的内容，可以不加花括号如果方法有参数，直接写在()里面
        new Thread(() -> {
            System.out.println("lambda polymorphic thread now is running!");
        }).start();
    }

    //遍历List
    static void eachList() {
        List<String> list = new ArrayList();
        list.add("hu");
        list.add("yi");
        list.add("dao");
        //传统的遍历方法
        for (String i : list) {
            System.out.println("传统遍历：" + i);
        }
        // lambda遍历
        list.forEach((i) -> {
            System.out.println("lambda方法遍历：" + i);
        });
        list.forEach(System.out::println);
    }

    //遍历Map
    static void eachMap() {
        Map<String, Object> map = new HashMap();
        map.put("name", "zhang");
        map.put("age", 22);
        map.put("sex", "man");

        //传统的遍历map
        for (Map.Entry<String, Object> m : map.entrySet()) {
            System.out.println("传统方法遍历map：" + m.getKey() + ": " + m.getValue());
        }
        // lambda遍历map
        map.forEach((k, v) -> System.out.println("lambda遍历map: key:" + k + " ; value" + v));
    }

    //filter 对操作集合，按某个条件进行过滤。collection.stream().filter()
    //collect()方法是在原数据集的基础上进行更新，过程中不产生新的数据集
    static void streamFilter() {
        List<User> users = getUsers();
        System.out.println("对集合进行过滤：user name 包含 1 的用户");
        List<User> filtered = users.stream().filter(s -> s.getName().contains("1")).collect(Collectors.toList());
        filtered.forEach(user -> System.out.println("Filter过滤之后的数据：" + user.toString()));
    }

    //map 将对象转换为其他对象  collection.stream().map()
    static void streamMap() {
        List<User> users = getUsers();
        System.out.println("对集合进行操作：返回UserName 列表");
        List<String> nameList = users.stream().map(User::getName).collect(Collectors.toList());
        nameList.forEach(System.out::println);
        System.out.println("对集合进行操作：返回其他对象");
        List<NewUser> objList = users.stream().map(tmp -> {
            NewUser obj = new NewUser();
            obj.setName(tmp.getName());
            obj.setAge(tmp.getAge());
            return obj;
        }).collect(Collectors.toList());
        System.out.println(objList);
    }

    //mapReduce reduce实现的是将所有值合并为一个
    static void mapReduce() {
        List<Double> cost = Arrays.asList(10.0, 20.0, 30.0);
        double allCost = cost.stream().map(x -> x + x * 0.05).reduce((sum, x) -> sum + x).get();
        System.out.println(allCost);
    }

    // 结合filter做过滤
    static void filterPredicate() {
        List<String> languages = Arrays.asList("Java", "Python", "scala", "Shell", "R");
        System.out.println("Language starts with J: ");
        filterTest(languages, x -> x.startsWith("J"));
        System.out.println("\nLanguage ends with a: ");
        filterTest(languages, x -> x.endsWith("a"));
        System.out.println("\nAll languages: ");
        filterTest(languages, x -> true);
        System.out.println("\nNo languages: ");
        filterTest(languages, x -> false);
        System.out.println("\nLanguage length bigger three: ");
        filterTest(languages, x -> x.length() > 4);
    }

    static void filterTest(List<String> languages, Predicate<String> condition) {
        languages.stream().filter(x -> condition.test(x)).forEach(x -> System.out.println(x + " "));
    }

    static List<User> getUsers() {
        List<User> users = new ArrayList<>();
        User user1 = new User(1, "huang", 21);
        User user2 = new User(2, "fu1", 22);
        User user3 = new User(3, "dao", 23);
        User user4 = new User(4, "hui1", 24);
        users.add(user1);
        users.add(user2);
        users.add(user3);
        users.add(user4);
        return users;
    }
}

class User {

    public User(int age, String name, int core) {
        this.age = age;
        this.name = name;
        this.core = core;
    }

    private int age;
    private String name;
    private int core;

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getCore() {
        return core;
    }

    public void setCore(int core) {
        this.core = core;
    }

    @Override
    public String toString() {
        return "User{" +
                "age=" + age +
                ", name='" + name + '\'' +
                ", core=" + core +
                '}';
    }
}

class NewUser {

    public NewUser() {
    }

    public NewUser(int age, String name, int core) {
        this.age = age;
        this.name = name;
        this.core = core;
    }

    private int age;
    private String name;
    private int core;

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getCore() {
        return core;
    }

    public void setCore(int core) {
        this.core = core;
    }

    @Override
    public String toString() {
        return "User{" +
                "age=" + age +
                ", name='" + name + '\'' +
                ", core=" + core +
                '}';
    }
}